{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 52,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "b'\\x00\\x00\\x00\\x02'"
      ]
     },
     "execution_count": 52,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import struct\n",
    "struct.pack('>i',2) # 高位字节"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 53,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "47040000\n"
     ]
    }
   ],
   "source": [
    "import struct\n",
    "with open('./MNIST_data/train-images-idx3-ubyte','rb') as f:\n",
    "    buffer = f.read(4*4)\n",
    "    head = struct.unpack('>iiii',buffer)\n",
    "    length = head[1]*head[2]*head[3]\n",
    "    print(length)\n",
    "    buffer = f.read(length)\n",
    "    data = struct.unpack(f'>{length}B',buffer)\n",
    "    "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 54,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(60000, 28, 28)"
      ]
     },
     "execution_count": 54,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "imgs = np.reshape(data,(head[1],head[2],head[3]))\n",
    "imgs.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAPsAAAD4CAYAAAAq5pAIAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4xLjEsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy8QZhcZAAAOv0lEQVR4nO3df6zV9X3H8deLuysqioFaKKV2VIVa5laot1hnW2xNDbpkaFLbksUy50KTVofVbTVuSU2XLK6xde2K7WilYn9gmqiVNM5KGZmztdQLUkHRYikowmCCm7/xXu57f9yvy1Xv93MO53zPD+7n+Uhuzrnf9/mc7zsHXvd7zvmc7/k4IgRg7BvX6QYAtAdhBzJB2IFMEHYgE4QdyMTvtXNnR3l8HK0J7dwlkJVX9KJejYMerdZU2G0vkPQ1ST2SvhMR16duf7Qm6Eyf28wuASSsj7WltYafxtvukbRM0vmSZktaZHt2o/cHoLWaec0+T9ITEbE9Il6VdJukhdW0BaBqzYR9uqSnRvy+q9j2OraX2O633T+gg03sDkAzmgn7aG8CvOmztxGxPCL6IqKvV+Ob2B2AZjQT9l2SThrx+zsk7W6uHQCt0kzYH5Q00/a7bB8l6VOSVlfTFoCqNTz1FhGDti+X9FMNT72tiIhHKusMQKWammePiLsl3V1RLwBaiI/LApkg7EAmCDuQCcIOZIKwA5kg7EAmCDuQCcIOZIKwA5kg7EAmCDuQCcIOZIKwA5kg7EAmCDuQCcIOZIKwA5kg7EAmCDuQCcIOZIKwA5lo65LNGHsGP3pGsr7ns+VLfv36rJXJse99YHGy/vZlRyXrPes2Juu54cgOZIKwA5kg7EAmCDuQCcIOZIKwA5kg7EAmmGdH0tD8ucn611d8I1k/tbf8v9hQjX0/dNZ3k/XH+w4l638z4wM19pCXpsJue4ek5yUdkjQYEX1VNAWgelUc2T8SEc9UcD8AWojX7EAmmg17SLrX9gbbS0a7ge0ltvtt9w+o/HPSAFqr2afxZ0fEbttTJK2x/VhE3DfyBhGxXNJySZroydHk/gA0qKkje0TsLi73SbpT0rwqmgJQvYbDbnuC7eNfuy7pPElbqmoMQLWaeRo/VdKdtl+7nx9GxD2VdIW2GTgvPVv6tzd9L1mf1Zs+p3woMZu+fWAgOfZ/h8Yn63PTZR08//2ltWPWbU6OHXrllfSdH4EaDntEbJf03gp7AdBCTL0BmSDsQCYIO5AJwg5kgrADmeAU1zGgZ+LE0tqLHz4tOfbzN/4wWf/IMS/U2Hvjx4tbnv3jZH3tTWcl6z+/7uvJ+prvfKu0Nvv7lyfHnvyFB5L1IxFHdiAThB3IBGEHMkHYgUwQdiAThB3IBGEHMsE8+xiw69bppbUH37+sjZ0cni9NeTBZv+e49Dz8pTvOS9ZXzvhZaW3i7P3JsWMRR3YgE4QdyARhBzJB2IFMEHYgE4QdyARhBzLBPPsRYPCjZyTrq+aUL5s8Tumveq7l0p3nJuv9P3tPsr75svLe1r18dHLslP6Xk/Unnk2fq9/7j+tKa+OcHDomcWQHMkHYgUwQdiAThB3IBGEHMkHYgUwQdiATjoi27WyiJ8eZTs/b5mho/txk/Z9X3pSsn9rb+Mcl/vSxi5L1no+/mKwf+JN3J+v7Ty+f0J617Knk2MGndiXrtfzk6Q2ltT2H0nP4f7H4r5L1nnUbG+qp1dbHWj0XB0Z90Gse2W2vsL3P9pYR2ybbXmN7W3E5qcqGAVSvnqfxt0ha8IZt10haGxEzJa0tfgfQxWqGPSLuk3TgDZsXSlpZXF8p6cKK+wJQsUbfoJsaEXskqbicUnZD20ts99vuH9DBBncHoFktfzc+IpZHRF9E9PVqfKt3B6BEo2Hfa3uaJBWX+6prCUArNBr21ZIWF9cXS7qrmnYAtErNCVrbqySdI+lE27skfVHS9ZJ+ZPsySU9KuriVTR7pfMYfJOvPXJWe853Vmz4nfUPirZB/f2F2cuz+205K1t/ybHqd8hO+/8t0PVEbTI5srak96ZeU+698KVmfUn6qfNeqGfaIWFRS4tMxwBGEj8sCmSDsQCYIO5AJwg5kgrADmeCrpCsw7thjk/XBLz+XrP/ytDuS9d8NvpqsX3Xt1aW1Sf/5ZHLslAnpz0MdSlbHrnnTdibrO9rTRqU4sgOZIOxAJgg7kAnCDmSCsAOZIOxAJgg7kAnm2Svw8vz0Kaw/PS39VdC1/OXSzyfrx/+4/DTTTp5Giu7CkR3IBGEHMkHYgUwQdiAThB3IBGEHMkHYgUwwz16BP/qHTcn6uBp/Uy/dmf6i3mN+/KvD7glSr3tKawM1VirvcfuWMm8XjuxAJgg7kAnCDmSCsAOZIOxAJgg7kAnCDmSCefY6/c8lZ5XW/n7qDcmxQ6qx5PK96WWV36lfJOsY3UCUf+v9kIaSY+/Zmv43mamNDfXUSTWP7LZX2N5ne8uIbdfZftr2puLngta2CaBZ9TyNv0XSglG23xgRc4qfu6ttC0DVaoY9Iu6TdKANvQBooWbeoLvc9sPF0/xJZTeyvcR2v+3+AR1sYncAmtFo2L8p6RRJcyTtkfSVshtGxPKI6IuIvl6Nb3B3AJrVUNgjYm9EHIqIIUnfljSv2rYAVK2hsNueNuLXiyRtKbstgO5Qc57d9ipJ50g60fYuSV+UdI7tOZJCw0tVf6aFPXaFwWPKayeMS8+jP/BK+uXLybfuTu87WR27aq17/9gNp9e4hw2llT/bfn5y5GlLf5esH4nr1tcMe0QsGmXzzS3oBUAL8XFZIBOEHcgEYQcyQdiBTBB2IBOc4toG+w8dl6wPbt/Rnka6TK2ptcev/8Nk/bGF30jW/+2lE0pru5edmhx7/LPly2AfqTiyA5kg7EAmCDuQCcIOZIKwA5kg7EAmCDuQCebZ2+Cvf35xsj4rcSrmkW5o/tzS2r6rXk6O3dqXnkc/d/Mnk/UJC7aX1o7X2JtHr4UjO5AJwg5kgrADmSDsQCYIO5AJwg5kgrADmWCevV4uL42r8Tfzax9clawv06xGOuoKO79UvpS1JN3+6a+W1mb1pr+C+32/Wpysv/2iR5N1vB5HdiAThB3IBGEHMkHYgUwQdiAThB3IBGEHMsE8e72ivDSkoeTQ+cfsT9avvOWMZP2U76bvv/e/ni+t7Z3/1uTYyZ/claxf8c61yfr5x6bPxV/94tTS2qc3L0iOPfFfJyTrODw1j+y2T7K9zvZW24/YXlpsn2x7je1txeWk1rcLoFH1PI0flHR1RLxH0gckfc72bEnXSFobETMlrS1+B9ClaoY9IvZExMbi+vOStkqaLmmhpJXFzVZKurBVTQJo3mG9QWd7hqS5ktZLmhoRe6ThPwiSppSMWWK733b/gA421y2AhtUddtvHSbpd0pUR8Vy94yJieUT0RURfr8Y30iOACtQVdtu9Gg76DyLijmLzXtvTivo0Sfta0yKAKtScerNtSTdL2hoRI89XXC1psaTri8u7WtLhGHC00w/z1o99K1m//0NHJ+vbDr6ttHbpCTuSY5u1dPeHkvV7fjGntDZzaX5f59xJ9cyzny3pEkmbbW8qtl2r4ZD/yPZlkp6UlP5ydAAdVTPsEXG/yr+64dxq2wHQKnxcFsgEYQcyQdiBTBB2IBOEHciEIxLnblZsoifHmT4y38DvmXVKaW3Wqp3Jsf/0tgea2netr6qudYptykMH0/e96D+WJOuzLh27y00fidbHWj0XB0adPePIDmSCsAOZIOxAJgg7kAnCDmSCsAOZIOxAJvgq6Tod+s1vS2vbLp6RHDv7iiuS9Uc/8S+NtFSX0+7+bLL+7pteStZnPcQ8+ljBkR3IBGEHMkHYgUwQdiAThB3IBGEHMkHYgUxwPjswhnA+OwDCDuSCsAOZIOxAJgg7kAnCDmSCsAOZqBl22yfZXmd7q+1HbC8ttl9n+2nbm4qfC1rfLoBG1fPlFYOSro6IjbaPl7TB9pqidmNE3NC69gBUpZ712fdI2lNcf972VknTW90YgGod1mt22zMkzZW0vth0ue2Hba+wPalkzBLb/bb7B3SwqWYBNK7usNs+TtLtkq6MiOckfVPSKZLmaPjI/5XRxkXE8ojoi4i+Xo2voGUAjagr7LZ7NRz0H0TEHZIUEXsj4lBEDEn6tqR5rWsTQLPqeTfekm6WtDUivjpi+7QRN7tI0pbq2wNQlXrejT9b0iWSNtveVGy7VtIi23MkhaQdkj7Tkg4BVKKed+PvlzTa+bF3V98OgFbhE3RAJgg7kAnCDmSCsAOZIOxAJgg7kAnCDmSCsAOZIOxAJgg7kAnCDmSCsAOZIOxAJgg7kIm2Ltls+78l7Ryx6URJz7StgcPTrb11a18SvTWqyt5+PyLeOlqhrWF/087t/ojo61gDCd3aW7f2JdFbo9rVG0/jgUwQdiATnQ778g7vP6Vbe+vWviR6a1Rbeuvoa3YA7dPpIzuANiHsQCY6EnbbC2w/bvsJ29d0oocytnfY3lwsQ93f4V5W2N5ne8uIbZNtr7G9rbgcdY29DvXWFct4J5YZ7+hj1+nlz9v+mt12j6TfSPqYpF2SHpS0KCIebWsjJWzvkNQXER3/AIbtD0t6QdKtEXF6se3Lkg5ExPXFH8pJEfGFLuntOkkvdHoZ72K1omkjlxmXdKGkP1cHH7tEX59QGx63ThzZ50l6IiK2R8Srkm6TtLADfXS9iLhP0oE3bF4oaWVxfaWG/7O0XUlvXSEi9kTExuL685JeW2a8o49doq+26ETYp0t6asTvu9Rd672HpHttb7C9pNPNjGJqROyRhv/zSJrS4X7eqOYy3u30hmXGu+axa2T582Z1IuyjLSXVTfN/Z0fE+ySdL+lzxdNV1KeuZbzbZZRlxrtCo8ufN6sTYd8l6aQRv79D0u4O9DGqiNhdXO6TdKe6bynqva+toFtc7utwP/+vm5bxHm2ZcXXBY9fJ5c87EfYHJc20/S7bR0n6lKTVHejjTWxPKN44ke0Jks5T9y1FvVrS4uL6Ykl3dbCX1+mWZbzLlhlXhx+7ji9/HhFt/5F0gYbfkf+tpL/rRA8lfZ0s6dfFzyOd7k3SKg0/rRvQ8DOiyyS9RdJaSduKy8ld1Nv3JG2W9LCGgzWtQ719UMMvDR+WtKn4uaDTj12ir7Y8bnxcFsgEn6ADMkHYgUwQdiAThB3IBGEHMkHYgUwQdiAT/wfcBlFxJhYKlQAAAABJRU5ErkJggg==\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAPsAAAD4CAYAAAAq5pAIAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4xLjEsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy8QZhcZAAAOJElEQVR4nO3dbYxc5XnG8evC2AYMaWyoXRcMIcG8NaUmXQENVQvipQSpMSShwqkiVyJ1QJCGKqilVBV8oBJqIYiiNMUJlk1LIKkIwmpoieMiUKrGYUEGTB0wQQaMLZsXgU0p9np998MeRwvseWY9c+bF3P+ftJqZc8+Zc2u0157Zec45jyNCAD78Duh3AwB6g7ADSRB2IAnCDiRB2IEkDuzlxqZ5ehykGb3cJJDKu/pf7YqdnqjWUdhtXyDpNklTJH0nIm4qPf8gzdDpPqeTTQIoWBOra2ttf4y3PUXSNyV9RtLJkhbZPrnd1wPQXZ38z36apOcj4oWI2CXpXkkLm2kLQNM6CfuRkl4e93hTtew9bC+xPWx7eEQ7O9gcgE50EvaJvgT4wLG3EbE0IoYiYmiqpnewOQCd6CTsmyTNG/f4KEmbO2sHQLd0EvbHJM23faztaZIulbSymbYANK3tobeI2G37KkkPaWzobVlEPNNYZwAa1dE4e0Q8KOnBhnoB0EUcLgskQdiBJAg7kARhB5Ig7EAShB1IgrADSRB2IAnCDiRB2IEkCDuQBGEHkiDsQBKEHUiCsANJEHYgCcIOJEHYgSQIO5AEYQeSIOxAEoQdSIKwA0kQdiAJwg4kQdiBJAg7kARhB5Ig7EAShB1IoqMpm21vlLRD0qik3REx1ERTAJrXUdgrZ0fEaw28DoAu4mM8kESnYQ9JP7L9uO0lEz3B9hLbw7aHR7Szw80BaFenH+PPjIjNtmdLWmX75xHx6PgnRMRSSUsl6SOeFR1uD0CbOtqzR8Tm6nabpPslndZEUwCa13bYbc+wfdje+5LOl7SuqcYANKuTj/FzJN1ve+/rfDci/qORrgA0ru2wR8QLkn6rwV4AdBFDb0AShB1IgrADSRB2IAnCDiTRxIkwGGC7/qB8IuKLf7ynWL/iU48U61fPfG6fe9rrN7/z1WL9kC3lAy7f/HT58Otj7q7fl017aLi47ocRe3YgCcIOJEHYgSQIO5AEYQeSIOxAEoQdSIJx9g+BVy//ndra7X/xzeK6Q9NHi/UDWuwPFm88t1g/9Vdeqq09+eXbiuu20qq3T89aVFub9VBHm94vsWcHkiDsQBKEHUiCsANJEHYgCcIOJEHYgSQYZx8AnjqtWH/33PJFfO/7q7+vrf36gdOL61724nnF+os3n1Csz/jh2mL94UOOrq09cv/xxXXvm7+yWG9l+9rDa2uzOnrl/RN7diAJwg4kQdiBJAg7kARhB5Ig7EAShB1IgnH2AbDlqvK13X92TavzvuvH0i95/g+La+7+/Eixfshra4r18pXdpc1Lfru2tmZ+Z+ez//s7hxXrx93xcm1td0db3j+13LPbXmZ7m+1145bNsr3K9obqdmZ32wTQqcl8jF8u6YL3LbtW0uqImC9pdfUYwABrGfaIeFTSG+9bvFDSiur+CkkXNdwXgIa1+wXdnIjYIknV7ey6J9peYnvY9vCIynNzAeiern8bHxFLI2IoIoamFr5IAtBd7YZ9q+25klTdbmuuJQDd0G7YV0paXN1fLOmBZtoB0C0tx9lt3yPpLElH2N4k6XpJN0n6vu3LJL0k6ZJuNrm/23D76cX6s5+7vVgvz6AunbTq8traiddsLK47+trrLV69M5df0b39wI1/u7hYn/nyf3dt2/ujlmGPiLor7Z/TcC8AuojDZYEkCDuQBGEHkiDsQBKEHUiCU1wb8ItbzijWn/1cedrkt/a8W6xf8vMvFusnfPW52trojh3FdVs5YMaMYv31L5xSrC88tP4y1wfo4OK6J/7rlcX6ccsZWtsX7NmBJAg7kARhB5Ig7EAShB1IgrADSRB2IAnG2SdpypzaK29pxcX/WFx3T4uTVFuNo08778UWr9++AxacXKx/ctn6Yv3GOf/QYgv1Vyc6c+2lxTVPuKG87dEWW8Z7sWcHkiDsQBKEHUiCsANJEHYgCcIOJEHYgSQYZ58kH1Q/Xjw0vbMR34P/bFp528fMK9Y3XH5Ube38c58orvvns5cW60cfWD7nvNUY/2jUT+rs7x1RXvfNDS1eHfuCPTuQBGEHkiDsQBKEHUiCsANJEHYgCcIOJME4+yTFuztra2t2Ti2ue/r0kWL9gR/fW6y3Oh++Ez/+v/JY94aR+nFySTr74LeL9eFd9ccQfPQurvveSy337LaX2d5me924ZTfYfsX22urnwu62CaBTk/kYv1zSBRMsvzUiFlQ/DzbbFoCmtQx7RDwq6Y0e9AKgizr5gu4q209VH/Nn1j3J9hLbw7aHR1T/fy+A7mo37N+S9AlJCyRtkXRL3RMjYmlEDEXE0NTCxQcBdFdbYY+IrRExGhF7JH1b0mnNtgWgaW2F3fbccQ8vlrSu7rkABkPLcXbb90g6S9IRtjdJul7SWbYXSApJGyV9pYs9DoTRrdtqa9df8eXiujf/U/m68qeUT2fXv2wvn89+4yOfra0dv7w89/uBW98q1mffU/5u9ux5/1msL364/r05XsPFddGslmGPiEUTLL6zC70A6CIOlwWSIOxAEoQdSIKwA0kQdiAJTnFtwLSHykNI1x3b3WOOjtfP2l53x8Jybz88+oFifSTK+4uDN7YYV0TPsGcHkiDsQBKEHUiCsANJEHYgCcIOJEHYgSQYZ09u98Hlv/cjUZ6OutVlro9d/lL9totromns2YEkCDuQBGEHkiDsQBKEHUiCsANJEHYgCcbZkzvs3p+Wn1A71w/2N+zZgSQIO5AEYQeSIOxAEoQdSIKwA0kQdiAJxtmT23HpGS2e8XhP+kD3tdyz255n+2Hb620/Y/tr1fJZtlfZ3lDdzux+uwDaNZmP8bslfT0iTpJ0hqQrbZ8s6VpJqyNivqTV1WMAA6pl2CNiS0Q8Ud3fIWm9pCMlLZS0onraCkkXdatJAJ3bpy/obH9M0qmS1kiaExFbpLE/CJJm16yzxPaw7eER7eysWwBtm3TYbR8q6T5JV0fE9smuFxFLI2IoIoamano7PQJowKTCbnuqxoJ+d0T8oFq81fbcqj5X0rbutAigCS2H3mxb0p2S1kfEN8aVVkpaLOmm6rY8ty8G0lsf51CLLCYzzn6mpC9Jetr22mrZdRoL+fdtXybpJUmXdKdFAE1oGfaI+Ikk15TPabYdAN3CZzggCcIOJEHYgSQIO5AEYQeS4BTX5I585J1ifepVU4r1kWiyG3QTe3YgCcIOJEHYgSQIO5AEYQeSIOxAEoQdSIJx9uT8X2uL9eXbJ7za2C8tOuyVYv2d35hbW5v28qbiumgWe3YgCcIOJEHYgSQIO5AEYQeSIOxAEoQdSIJxdhTdescXivVF19xWrM/9m+dra6+/eUp54z99qlzHPmHPDiRB2IEkCDuQBGEHkiDsQBKEHUiCsANJOKJ84W/b8yTdJenXJO2RtDQibrN9g6Q/lfRq9dTrIuLB0mt9xLPidDPx6/5kyhGHF+vT7isfqvG94/6ttvb7Ty4qrjvri68W66NvvlWsZ7QmVmt7vDHhrMuTOahmt6SvR8QTtg+T9LjtVVXt1oi4ualGAXTPZOZn3yJpS3V/h+31ko7sdmMAmrVP/7Pb/pikUyWtqRZdZfsp28tsz6xZZ4ntYdvDI9rZUbMA2jfpsNs+VNJ9kq6OiO2SviXpE5IWaGzPf8tE60XE0ogYioihqZreQMsA2jGpsNueqrGg3x0RP5CkiNgaEaMRsUfStyWd1r02AXSqZdhtW9KdktZHxDfGLR9/2dCLJa1rvj0ATZnMt/FnSvqSpKdt773u8HWSFtleICkkbZT0la50iL4afe31Yn3X58tDcyfdUv9rsf7cO4rrfvbEy4p1ToHdN5P5Nv4nkiYatyuOqQMYLBxBByRB2IEkCDuQBGEHkiDsQBKEHUii5SmuTeIUV6C7Sqe4smcHkiDsQBKEHUiCsANJEHYgCcIOJEHYgSR6Os5u+1VJL45bdISk13rWwL4Z1N4GtS+J3trVZG/HRMSvTlToadg/sHF7OCKG+tZAwaD2Nqh9SfTWrl71xsd4IAnCDiTR77Av7fP2Swa1t0HtS6K3dvWkt77+zw6gd/q9ZwfQI4QdSKIvYbd9ge1nbT9v+9p+9FDH9kbbT9tea3u4z70ss73N9rpxy2bZXmV7Q3U74Rx7fertBtuvVO/dWtsX9qm3ebYftr3e9jO2v1Yt7+t7V+irJ+9bz/9ntz1F0nOSzpO0SdJjkhZFxP/0tJEatjdKGoqIvh+AYfv3JL0t6a6I+GS17O8kvRERN1V/KGdGxF8OSG83SHq739N4V7MVzR0/zbikiyT9ifr43hX6+iP14H3rx579NEnPR8QLEbFL0r2SFvahj4EXEY9KeuN9ixdKWlHdX6GxX5aeq+ltIETEloh4orq/Q9Leacb7+t4V+uqJfoT9SEkvj3u8SYM133tI+pHtx20v6XczE5gTEVuksV8eSbP73M/7tZzGu5feN834wLx37Ux/3ql+hH2i62MN0vjfmRHxKUmfkXRl9XEVkzOpabx7ZYJpxgdCu9Ofd6ofYd8kad64x0dJ2tyHPiYUEZur222S7tfgTUW9de8MutXttj7380uDNI33RNOMawDeu35Of96PsD8mab7tY21Pk3SppJV96OMDbM+ovjiR7RmSztfgTUW9UtLi6v5iSQ/0sZf3GJRpvOumGVef37u+T38eET3/kXShxr6R/4Wkv+5HDzV9fVzSk9XPM/3uTdI9GvtYN6KxT0SXSTpc0mpJG6rbWQPU2z9LelrSUxoL1tw+9fa7GvvX8ClJa6ufC/v93hX66sn7xuGyQBIcQQckQdiBJAg7kARhB5Ig7EAShB1IgrADSfw/oeMroOOeN3sAAAAASUVORK5CYII=\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "for i in range(5):\n",
    "    plt.imshow(imgs[i])\n",
    "    plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 55,
   "metadata": {},
   "outputs": [],
   "source": [
    "from sklearn.datasets import fetch_mldata\n",
    "mnist = fetch_mldata('MNIST original', data_home='./')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 56,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'DESCR': 'mldata.org dataset: mnist-original',\n",
       " 'COL_NAMES': ['label', 'data'],\n",
       " 'target': array([0., 0., 0., ..., 9., 9., 9.]),\n",
       " 'data': array([[0, 0, 0, ..., 0, 0, 0],\n",
       "        [0, 0, 0, ..., 0, 0, 0],\n",
       "        [0, 0, 0, ..., 0, 0, 0],\n",
       "        ...,\n",
       "        [0, 0, 0, ..., 0, 0, 0],\n",
       "        [0, 0, 0, ..., 0, 0, 0],\n",
       "        [0, 0, 0, ..., 0, 0, 0]], dtype=uint8)}"
      ]
     },
     "execution_count": 56,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "mnist"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 57,
   "metadata": {},
   "outputs": [],
   "source": [
    "X, y = mnist['data'], mnist['target']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 58,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(70000, 784)"
      ]
     },
     "execution_count": 58,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "X.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 59,
   "metadata": {},
   "outputs": [],
   "source": [
    "%matplotlib inline\n",
    "import matplotlib\n",
    "import matplotlib.pyplot as plt"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 60,
   "metadata": {},
   "outputs": [],
   "source": [
    "some_digit = X[36000]\n",
    "some_digit_image = some_digit.reshape(28, 28)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 61,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.imshow(some_digit_image, cmap = matplotlib.cm.binary)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 62,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "5.0"
      ]
     },
     "execution_count": 62,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "y[36000]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 建立测试集和训练集"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 63,
   "metadata": {},
   "outputs": [],
   "source": [
    "X_train, X_test, y_train, y_test = X[:60000], X[60000:], y[:60000], y[60000:]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 训练一个二元分类器"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 64,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 6900, 56547, 11730, ..., 41010, 19844, 28020])"
      ]
     },
     "execution_count": 64,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 将数据集合交叉洗牌，交叉验证时，每个子集合数据分布均匀，有些机器学习算法对训练实例的顺序敏感\n",
    "import numpy as np\n",
    "shuffle_index = np.random.permutation(60000)\n",
    "shuffle_index"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 65,
   "metadata": {},
   "outputs": [],
   "source": [
    "X_train, y_train = X_train[shuffle_index], y_train[shuffle_index]\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 66,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0, 0, 0, ..., 0, 0, 0],\n",
       "       [0, 0, 0, ..., 0, 0, 0],\n",
       "       [0, 0, 0, ..., 0, 0, 0],\n",
       "       ...,\n",
       "       [0, 0, 0, ..., 0, 0, 0],\n",
       "       [0, 0, 0, ..., 0, 0, 0],\n",
       "       [0, 0, 0, ..., 0, 0, 0]], dtype=uint8)"
      ]
     },
     "execution_count": 66,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "X_train"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 训练一个二元分类器"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 67,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([False, False, False, ..., False, False, False])"
      ]
     },
     "execution_count": 67,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 识别数字5 ，二元分类5或者非5\n",
    "# 创建目标向量\n",
    "y_train_5 = (y_train == 5)\n",
    "y_train_5"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 68,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[False, False, False, ..., False, False,  True],\n",
       "       [False, False, False, ..., False, False, False],\n",
       "       [False, False, False, ..., False,  True, False],\n",
       "       ...,\n",
       "       [ True, False, False, ...,  True, False,  True],\n",
       "       [False, False, False, ..., False, False, False],\n",
       "       [False, False, False, ..., False, False, False]])"
      ]
     },
     "execution_count": 68,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "y_train_5.reshape(20, -1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 69,
   "metadata": {},
   "outputs": [],
   "source": [
    "y_test_5 = (y_test == 5) "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 70,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "D:\\Anaconda3\\lib\\site-packages\\sklearn\\linear_model\\stochastic_gradient.py:128: FutureWarning: max_iter and tol parameters have been added in <class 'sklearn.linear_model.stochastic_gradient.SGDClassifier'> in 0.19. If both are left unset, they default to max_iter=5 and tol=None. If tol is not None, max_iter defaults to max_iter=1000. From 0.21, default max_iter will be 1000, and default tol will be 1e-3.\n",
      "  \"and default tol will be 1e-3.\" % type(self), FutureWarning)\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "array([False])"
      ]
     },
     "execution_count": 70,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# SGD 梯度下降 分类器， 适合非常大的数据集，独立处理训练集数据，一次一个，适合在线学习，\n",
    "from sklearn.linear_model import SGDClassifier\n",
    "\n",
    "sgd_clf = SGDClassifier(random_state = 42)\n",
    "sgd_clf.fit(X_train, y_train_5)\n",
    "\n",
    "sgd_clf.predict([some_digit])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 性能考核"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 使用交叉验证测量精度"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 71,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "D:\\Anaconda3\\lib\\site-packages\\sklearn\\linear_model\\stochastic_gradient.py:128: FutureWarning: max_iter and tol parameters have been added in <class 'sklearn.linear_model.stochastic_gradient.SGDClassifier'> in 0.19. If both are left unset, they default to max_iter=5 and tol=None. If tol is not None, max_iter defaults to max_iter=1000. From 0.21, default max_iter will be 1000, and default tol will be 1e-3.\n",
      "  \"and default tol will be 1e-3.\" % type(self), FutureWarning)\n",
      "D:\\Anaconda3\\lib\\site-packages\\sklearn\\linear_model\\stochastic_gradient.py:128: FutureWarning: max_iter and tol parameters have been added in <class 'sklearn.linear_model.stochastic_gradient.SGDClassifier'> in 0.19. If both are left unset, they default to max_iter=5 and tol=None. If tol is not None, max_iter defaults to max_iter=1000. From 0.21, default max_iter will be 1000, and default tol will be 1e-3.\n",
      "  \"and default tol will be 1e-3.\" % type(self), FutureWarning)\n",
      "D:\\Anaconda3\\lib\\site-packages\\sklearn\\linear_model\\stochastic_gradient.py:128: FutureWarning: max_iter and tol parameters have been added in <class 'sklearn.linear_model.stochastic_gradient.SGDClassifier'> in 0.19. If both are left unset, they default to max_iter=5 and tol=None. If tol is not None, max_iter defaults to max_iter=1000. From 0.21, default max_iter will be 1000, and default tol will be 1e-3.\n",
      "  \"and default tol will be 1e-3.\" % type(self), FutureWarning)\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "array([0.96725, 0.96415, 0.96425])"
      ]
     },
     "execution_count": 71,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 评估分类器比评估回归器要困难得多\n",
    "\n",
    "# 3个折叠，正确率达到 95% 以上\n",
    "from sklearn.model_selection import cross_val_score\n",
    "cross_val_score(sgd_clf, X_train, y_train_5, cv=3, scoring=\"accuracy\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 72,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 把每张图都分类成 非5\n",
    "from sklearn.base import BaseEstimator\n",
    "class Never5Classifier(BaseEstimator):\n",
    "    def fit(self, X, y=None):\n",
    "        pass\n",
    "    def predict(self, X):\n",
    "        return np.zeros((len(X), 1), dtype=bool)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 73,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[False],\n",
       "       [False],\n",
       "       [False],\n",
       "       ...,\n",
       "       [False],\n",
       "       [False],\n",
       "       [False]])"
      ]
     },
     "execution_count": 73,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.zeros((len(X), 1), dtype=bool)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 74,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([0.90975, 0.9117 , 0.9075 ])"
      ]
     },
     "execution_count": 74,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "never_5_clf = Never5Classifier()\n",
    "cross_val_score(never_5_clf, X_train, y_train_5, cv=3, scoring=\"accuracy\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 混淆矩阵"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 75,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "D:\\Anaconda3\\lib\\site-packages\\sklearn\\linear_model\\stochastic_gradient.py:128: FutureWarning: max_iter and tol parameters have been added in <class 'sklearn.linear_model.stochastic_gradient.SGDClassifier'> in 0.19. If both are left unset, they default to max_iter=5 and tol=None. If tol is not None, max_iter defaults to max_iter=1000. From 0.21, default max_iter will be 1000, and default tol will be 1e-3.\n",
      "  \"and default tol will be 1e-3.\" % type(self), FutureWarning)\n",
      "D:\\Anaconda3\\lib\\site-packages\\sklearn\\linear_model\\stochastic_gradient.py:128: FutureWarning: max_iter and tol parameters have been added in <class 'sklearn.linear_model.stochastic_gradient.SGDClassifier'> in 0.19. If both are left unset, they default to max_iter=5 and tol=None. If tol is not None, max_iter defaults to max_iter=1000. From 0.21, default max_iter will be 1000, and default tol will be 1e-3.\n",
      "  \"and default tol will be 1e-3.\" % type(self), FutureWarning)\n",
      "D:\\Anaconda3\\lib\\site-packages\\sklearn\\linear_model\\stochastic_gradient.py:128: FutureWarning: max_iter and tol parameters have been added in <class 'sklearn.linear_model.stochastic_gradient.SGDClassifier'> in 0.19. If both are left unset, they default to max_iter=5 and tol=None. If tol is not None, max_iter defaults to max_iter=1000. From 0.21, default max_iter will be 1000, and default tol will be 1e-3.\n",
      "  \"and default tol will be 1e-3.\" % type(self), FutureWarning)\n"
     ]
    }
   ],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "* 准确率超过90% ，因为5的图像大约只有10%，你猜一张图不是5， 90%的时间你都是正确的\n",
    "* 这说明准确率无法成为分类器的首要性能指标，特别是当你处理偏科数据集， 某些类比其他类更为频繁"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 76,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "D:\\Anaconda3\\lib\\site-packages\\sklearn\\linear_model\\stochastic_gradient.py:128: FutureWarning: max_iter and tol parameters have been added in <class 'sklearn.linear_model.stochastic_gradient.SGDClassifier'> in 0.19. If both are left unset, they default to max_iter=5 and tol=None. If tol is not None, max_iter defaults to max_iter=1000. From 0.21, default max_iter will be 1000, and default tol will be 1e-3.\n",
      "  \"and default tol will be 1e-3.\" % type(self), FutureWarning)\n",
      "D:\\Anaconda3\\lib\\site-packages\\sklearn\\linear_model\\stochastic_gradient.py:128: FutureWarning: max_iter and tol parameters have been added in <class 'sklearn.linear_model.stochastic_gradient.SGDClassifier'> in 0.19. If both are left unset, they default to max_iter=5 and tol=None. If tol is not None, max_iter defaults to max_iter=1000. From 0.21, default max_iter will be 1000, and default tol will be 1e-3.\n",
      "  \"and default tol will be 1e-3.\" % type(self), FutureWarning)\n",
      "D:\\Anaconda3\\lib\\site-packages\\sklearn\\linear_model\\stochastic_gradient.py:128: FutureWarning: max_iter and tol parameters have been added in <class 'sklearn.linear_model.stochastic_gradient.SGDClassifier'> in 0.19. If both are left unset, they default to max_iter=5 and tol=None. If tol is not None, max_iter defaults to max_iter=1000. From 0.21, default max_iter will be 1000, and default tol will be 1e-3.\n",
      "  \"and default tol will be 1e-3.\" % type(self), FutureWarning)\n"
     ]
    }
   ],
   "source": [
    "# 评估分类器性能的更好方法是混淆矩阵\n",
    "# A类别实例被分为B类别次数\n",
    "# 想要知道分类器将数字3和数字5混淆多少次，通过混淆矩阵的5行3列\n",
    "from sklearn.model_selection import cross_val_predict\n",
    "\n",
    "y_train_pred = cross_val_predict(sgd_clf, X_train, y_train_5, cv=3)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 与 cross_val_score 相比\n",
    "* 同样执行交叉验证\n",
    "* 返回的不是评估分数，是每个折叠的预测\n",
    "* 每一个实例在模型预测时使用的数据，在训练期间从未见过"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 77,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[53888,   691],\n",
       "       [ 1396,  4025]], dtype=int64)"
      ]
     },
     "execution_count": 77,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from sklearn.metrics import confusion_matrix\n",
    "\n",
    "confusion_matrix(y_train_5, y_train_pred)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 78,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 行表示实际类别，列表示预测类别\n",
    "# 第一行 第一列 53272 被正确的分为 非5 ，真负类\n",
    "# 第一行 第二列 1307 被错误的分类成 5 ，假正类\n",
    "# 第二行 第一列 1077 张被错误的分为 非5， 假负类\n",
    "# 第二行 第二列 4344 张被正确的分在了5 ，真正类\n",
    "# 这种衡量方式太复杂，我们可以用更简单的指标"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 79,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[54579,     0],\n",
       "       [    0,  5421]], dtype=int64)"
      ]
     },
     "execution_count": 79,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "y_train_perfect_predictions = y_train_5\n",
    "confusion_matrix(y_train_5, y_train_perfect_predictions)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 精度和召回率"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 81,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.8534775233248516"
      ]
     },
     "execution_count": 81,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 82,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.7424829367275411"
      ]
     },
     "execution_count": 82,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 正类预测的准确率 被称为分类器的精度\n",
    "\n",
    "\n",
    "$\n",
    "\\text{精度} = \\cfrac{TP}{TP + FP}\n",
    "$\n",
    "\n",
    "TP是真正类的数量，FP是假正类的数量\n",
    "\n",
    "\n",
    "\n",
    "$\n",
    "\\text{召回率TPR} = \\cfrac{TP}{TP + FN}\n",
    "$\n",
    "* 检测正类实例的比例\n",
    "FN是假负类的数量\n",
    "![jupyter](./zhaohui.jpg)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 83,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.8534775233248516"
      ]
     },
     "execution_count": 83,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from sklearn.metrics import precision_score, recall_score\n",
    "\n",
    "precision_score(y_train_5, y_train_pred) # 4327 / 4327 + 1276"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 84,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.7424829367275411"
      ]
     },
     "execution_count": 84,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "recall_score(y_train_5, y_train_pred)    #  4327 / 4327 + 1094"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 85,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 说明 检测一张图的时候，只有90%的概率是准确的，而且只有64%的数字5 被它检测出来\n",
    "# 精度和召回率合成单一指标，成为 F1 分数，谐波平均值\n",
    "# 平均值平等对待所有的值，谐波平均值会给予较低值更高的权重，只有召回率和精度都很高时，才能获得较高的F1分数"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "$\n",
    "F_1 = \\cfrac{2}{\\cfrac{1}{\\text{precision}} + \\cfrac{1}{\\text{recall}}} = 2 \\times \\cfrac{\\text{precision}\\, \\times \\, \\text{recall}}{\\text{precision}\\, + \\, \\text{recall}} = \\cfrac{TP}{TP + \\cfrac{FN + FP}{2}}\n",
    "$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 86,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.7941205484857453"
      ]
     },
     "execution_count": 86,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from sklearn.metrics import f1_score\n",
    "f1_score(y_train_5, y_train_pred)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 87,
   "metadata": {},
   "outputs": [],
   "source": [
    "# F1分数对那些具有相近精度和召回率 分类器更有利，这不一定符合你的期望\n",
    "# 有时候你更关心精度，有时你能关心召回率\n",
    "# 训练一个分类器检测儿童可以放心观看的视频，你可能要求拦截了很多好的视频，低召回率，保留下来的都是安全的视频，高精度\n",
    "# 不能同时增加精度并减少召回率，反之亦然"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 精度/召回率权衡"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "​\n",
    "\n",
    "![jupyter](./quanheng.jpg)\n",
    "\n",
    "    SGDClassifier对每个实例基于决策函数计算一个分值，大于阀值为正类，否则为负类\n",
    "    中间阀值右侧找到4个真正类 真5 ， 一个假正类 6， 精度为 4/5 80%\n",
    "    在所有的6个 真正的5 中，分类器找到了4个，召回率为 4/6 67%\n",
    "    提高阀值，向右移动，精度提高，召回降低\n",
    "    反之阀值降低，召回提高，精度降低\n",
    "    SKlearn不可以直接设置阀值，可以访问决策分数，\n",
    "    SGDClassifier 默认阀值为0\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 如何设置阀值\n",
    "\n",
    "# 用predict_proba得到每个实例属于正类的概率，然后对概率切一下。以LogisticRegression为例\n",
    "# clf = LogisticRegression()\n",
    "# clf.fit(X_train, y_train)\n",
    "# pred_proba = clf.predict_proba(X_test)[:, 1]\n",
    "# threshold = 0.75  # 阀值设置为0.75\n",
    "# pred_label = pred_proba > threshold\n",
    "\n",
    "# pred_proba是每个实例为真的概率\n",
    "# 假设阈值是0.75\n",
    "# pred_label里True就是概率大于0.75的"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 88,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([-35434.24348367])"
      ]
     },
     "execution_count": 88,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 返回决策值decision_function\n",
    "y_scores = sgd_clf.decision_function([some_digit])\n",
    "y_scores"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.5814425382770706"
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 得到召回率\n",
    "recall_score(y_train_5,y_train_pred)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 183,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 说明 检测一张图的时候，只有90%的概率是准确的，而且只有64%的数字5 被它检测出来\n",
    "# 精度和召回率合成单一指标，成为 F1 分数，谐波平均值\n",
    "# 平均值平等对待所有的值，谐波平均值会给予较低值更高的权重，只有召回率和精度都很高时，才能获得较高的F1分数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.7161195047143017"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from sklearn.metrics import f1_score\n",
    "# 得到f1分数\n",
    "f1_score(y_train_5,y_train_pred)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [],
   "source": [
    "# F1分数对那些具有相近精度和召回率 分类器更有利，这不一定符合你的期望\n",
    "# 有时候你更关心精度，有时你能关心召回率\n",
    "# 训练一个分类器检测儿童可以放心观看的视频，你可能要求拦截了很多好的视频，低召回率，保留下来的都是安全的视频，高精度\n",
    "# 不能同时增加精度并减少召回率，反之亦然"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "精度/召回率权衡\n",
    "\n",
    "​\n",
    "\n",
    "![jupyter](./quanheng.jpg)\n",
    "\n",
    "    SGDClassifier对每个实例基于决策函数计算一个分值，大于阀值为正类，否则为负类\n",
    "    中间阀值右侧找到4个真正类 真5 ， 一个假正类 6， 精度为 4/5 80%\n",
    "    在所有的6个 真正的5 中，分类器找到了4个，召回率为 4/6 67%\n",
    "    提高阀值，向右移动，精度提高，召回降低\n",
    "    反之阀值降低，召回提高，精度降低\n",
    "    SKlearn不可以直接设置阀值，可以访问决策分数，\n",
    "    SGDClassifier 默认阀值为0\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 如何设置阀值\n",
    "\n",
    "# 用predict_proba得到每个实例属于正类的概率，然后对概率切一下。以LogisticRegression为例\n",
    "# clf = LogisticRegression()\n",
    "# clf.fit(X_train, y_train)\n",
    "# pred_proba = clf.predict_proba(X_test)[:, 1]\n",
    "# threshold = 0.75  # 阀值设置为0.75\n",
    "# pred_label = pred_proba > threshold\n",
    "\n",
    "# pred_proba是每个实例为真的概率\n",
    "# 假设阈值是0.75\n",
    "# pred_label里True就是概率大于0.75的"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([35091.31170437])"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 返回决策值decision_function\n",
    "y_scores = scif.decision_function([some_digit])\n",
    "y_scores"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 89,
   "metadata": {},
   "outputs": [],
   "source": [
    "threshold = 0\n",
    "y_some_digit_pred = (y_scores > threshold)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 122,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([False])"
      ]
     },
     "execution_count": 122,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "y_some_digit_pred"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 91,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([False])"
      ]
     },
     "execution_count": 91,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 提高阀值可以降低召回率，提高阀值到200000，就错了这个图\n",
    "threshold = 200000\n",
    "y_some_digit_pred = (y_scores > threshold)\n",
    "y_some_digit_pred"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 93,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "D:\\Anaconda3\\lib\\site-packages\\sklearn\\linear_model\\stochastic_gradient.py:128: FutureWarning: max_iter and tol parameters have been added in <class 'sklearn.linear_model.stochastic_gradient.SGDClassifier'> in 0.19. If both are left unset, they default to max_iter=5 and tol=None. If tol is not None, max_iter defaults to max_iter=1000. From 0.21, default max_iter will be 1000, and default tol will be 1e-3.\n",
      "  \"and default tol will be 1e-3.\" % type(self), FutureWarning)\n",
      "D:\\Anaconda3\\lib\\site-packages\\sklearn\\linear_model\\stochastic_gradient.py:128: FutureWarning: max_iter and tol parameters have been added in <class 'sklearn.linear_model.stochastic_gradient.SGDClassifier'> in 0.19. If both are left unset, they default to max_iter=5 and tol=None. If tol is not None, max_iter defaults to max_iter=1000. From 0.21, default max_iter will be 1000, and default tol will be 1e-3.\n",
      "  \"and default tol will be 1e-3.\" % type(self), FutureWarning)\n",
      "D:\\Anaconda3\\lib\\site-packages\\sklearn\\linear_model\\stochastic_gradient.py:128: FutureWarning: max_iter and tol parameters have been added in <class 'sklearn.linear_model.stochastic_gradient.SGDClassifier'> in 0.19. If both are left unset, they default to max_iter=5 and tol=None. If tol is not None, max_iter defaults to max_iter=1000. From 0.21, default max_iter will be 1000, and default tol will be 1e-3.\n",
      "  \"and default tol will be 1e-3.\" % type(self), FutureWarning)\n"
     ]
    }
   ],
   "source": [
    "# 如何决定使用什么阀值\n",
    "# 返回决策值，而不是预测结果\n",
    "y_scores = cross_val_predict(sgd_clf, X_train, y_train_5, cv=3,\n",
    "                             method=\"decision_function\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 94,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(60000,)"
      ]
     },
     "execution_count": 94,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 有了y_scores，可以计算所有可能的阀值的精度和召回率\n",
    "y_scores.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 95,
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "from sklearn.metrics import precision_recall_curve\n",
    "# 精度值，召回率，决策值\n",
    "precisions, recalls, thresholds = precision_recall_curve(y_train_5, y_scores)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 97,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "D:\\Anaconda3\\lib\\site-packages\\matplotlib\\backends\\backend_agg.py:211: RuntimeWarning: Glyph 8722 missing from current font.\n",
      "  font.set_text(s, 0.0, flags=flags)\n",
      "D:\\Anaconda3\\lib\\site-packages\\matplotlib\\backends\\backend_agg.py:180: RuntimeWarning: Glyph 8722 missing from current font.\n",
      "  font.set_text(s, 0, flags=flags)\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 576x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "# 使用matplotlib 绘制精度和召回相对于阀值的函数图\n",
    "def plot_precision_recall_vs_threshold(precisions, recalls, thresholds):\n",
    "# 精度的曲线,linewidth(线的粗细),\n",
    "    plt.plot(thresholds, precisions[:-1], \"b--\", label=\"Precision\", linewidth=2)\n",
    "#     召回的曲线\n",
    "    plt.plot(thresholds, recalls[:-1], \"g-\", label=\"Recall\", linewidth=2)\n",
    "#     x轴的标签\n",
    "    plt.xlabel(\"Threshold\", fontsize=16)\n",
    "    plt.legend(loc=\"upper left\", fontsize=16)\n",
    "#     y轴的范围\n",
    "    plt.ylim([0, 1])\n",
    "\n",
    "plt.figure(figsize=(8, 4))\n",
    "plot_precision_recall_vs_threshold(precisions, recalls, thresholds)\n",
    "# x轴的范围\n",
    "plt.xlim([-700000, 700000])\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 98,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 576x432 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.rcParams['font.sans-serif'] = ['SimHei']\n",
    "def plot_precision_vs_recall(precisions, recalls):\n",
    "    plt.plot(recalls, precisions, \"b-\", linewidth=2)\n",
    "    plt.xlabel(\"召回\", fontsize=16)\n",
    "    plt.ylabel(\"精度\", fontsize=16)\n",
    "    plt.axis([0, 1, 0, 1])\n",
    "\n",
    "plt.figure(figsize=(8, 6))\n",
    "plot_precision_vs_recall(precisions, recalls)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 通过选择阀值来实现最佳的精度/召回率权衡"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 120,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 目标设定为90%的精度，阀值大概在30000左右 , 设置了阀值为30000\n",
    "y_train_pred_90 = (y_scores > 50000)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 121,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.9033560434014636"
      ]
     },
     "execution_count": 121,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "precision_score(y_train_5, y_train_pred_90)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 123,
   "metadata": {},
   "outputs": [],
   "source": [
    "from sklearn.metrics import roc_curve\n",
    "\n",
    "fpr, tpr, thresholds = roc_curve(y_train_5, y_scores)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 124,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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IPy/1T9xz/yv2JFbvPe5+FgPayYNJNGnj1REpD565JFHuPrqqznxxBOZM2cOxx57rNMl1TglVDVs2lXAqf9893fPL7q+D0elNXCgIhERqSlnnXUWP/74I1OmTCEuzp2LrbUjXxWs3rib8bNX8UvebxfpPTGqK4M7tKjV9xYRkdphrWXWrFm89dZbzJkzp16tyteOfLUgv9hP16nvUFQa/M3zt53Rnst6t3WoKhEROVQ5OTlceeWVvPDCC/Tt25e8vDwaNmzodFm1TqF/AFv2FNLznsW/eW7ime259JQ2uvRORKQeW7lyJcOHD+eHH37gzjvv5JZbbsHr9TpdVkQo9MthraXXvb8G/n0XZHB+18McrEhERGpCaWkpF154IcFgkCVLltCrVy+nS4oohf5+AkFL+0nzKVvq8NDwEzk7I93ZokRE5JDs2LGD1NRUYmNjefnllzniiCNITU11uqyIqz+rFiLk2hc/pSQQmsM/rX0zBb6ISD33zjvv0LFjR6ZMmQJA586dozLwQaH/G0u/28n/skJ75l/d72ieuvgkhysSEZGDVVpays0338zgwYNp3LgxF1xwgdMlOU7D+2H+QJCLnloGwKntmvK3we7blEFEJFps2LCB4cOHs3z5ci677DIeeOABEhMTnS7LcQr9sLMe+nDvPP7/XZjhbDEiInJIdu/ezYYNG5g3b546/H1oeJ/Qav2vtuYCMOyk1jRLjne4IhERqa78/Hz+/e9/A9ClSxc2bNigwN+PQh94+ZPNex/ffW5HBysREZGDsXbtWjIzMxk1ahRffPEFgIbzyxH1of/V1hxu/M9aAK7sexQejzbeERGpL6y1PProo3Tr1o09e/bwzjvv0KFDB6fLqrOiek4/ELQMn7EMf9Dii/Ew4bRjnC5JRESqYcyYMTz33HOcfvrpPPvsszRr1szpkuq0qA79aW9/ze6CUgDe/Msp+GKifuBDRKReGTRoEBkZGVx77bX16oY5Tona0A8ELY8v+Q6Afw3rzNHNkh2uSEREKhMIBLjrrrto2bIll112GSNGjHC6pHolan8smvb21wAk+ryc3Um77omI1HU//fQTAwYM4I477mDlypVOl1MvRW2nX9blj+l5pBbviYjUca+99hpjx46luLiYWbNmMXr0aKdLqpeiMvR355fsfTy+91EOViIiIpVZt24d55xzDp07d2bu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8cwzzwBw5plnsnz5cgW+/IbrQr80EAQgrWGcw5WIiESGtZann36azMxMbrvtNvLy8gDwerWuSX7LdaH/zbZcAI5rkexwJSIitS87O5vhw4czbtw4Tj75ZFatWkWDBrqluJTPdXP6jRJiAUiOi3W4EhGR2lVcXEy3bt347rvvuPvuu7nxxhvV3UuFXBf6BSUBAJoma3hfRNzJWosxhri4OCZMmECnTp3o2bOn02VJPeC64f3PNodW76cmqtMXEffZunUrp59+Om+99RYAV1xxhQJfqsxVob/vXaLS1OmLiMssWLCAjIwMlixZwi+//OJ0OVIPuSr0i0qDex8n6mY7IuISJSUl3HjjjQwePJi0tDRWrVqlzXbkoLgq9Mu24E1vFO9wJSIiNefVV19l2rRpXHHFFaxcuZIOHTo4XZLUU65qh3/YGdqY5+jmulxPROq/H3/8kcMPP5zzzz+fjz76SHP3csjc1envDHX6rVK0Ba+I1F/5+flccskldOjQgQ0bNmCMUeBLjXBVp//9L6FO/4gmiQ5XIiJycD799FOGDRvGN998w6233krr1q2dLklcxFWd/ooNOwF1+iJSPz388MN0796dnJwcFi5cyNSpU4mJcVVvJg5zVejvKSgFICFWO1KJSP3z2WefMXDgQLKysujfv7/T5YgLuepHyJ35JQC00m11RaSeWLJkCQ0bNuTEE0/koYceIjY2FqO7hEotcU2nb63FE/570qZpkrPFiIhUwu/3c8cdd9C/f38mTpwIgM/nU+BLrXJNp19QEiBowRiI1/C+iNRhmzZtYsSIEXzwwQeMHj2ahx9+2OmSJEq4JvR35BYDkN5IQ/siUnd9/vnn9O7dm9LSUmbPns3IkSOdLkmiiGuG97flFAHQrKH23BeRuuu4445j6NChrFmzRoEvEeea0C9bxNckSaEvInXLunXrOP300/nll1+IiYnhscceo127dk6XJVHINaGfWxS6XE+31BWRusJay9NPP01mZiarV6/mu+++c7okiXKuCf3vdoR240v0aRGfiDgvOzub4cOHM27cOHr06EFWVhbdu3d3uiyJcq4J/fiY0G9lV3iDHhERJ91www385z//4e6772bBggW0bNnS6ZJE3LN6f/32PACOa6E77ImIM4LBINnZ2aSmpnLXXXcxduxYevTo4XRZInu5JvQbJYTm8gNB63Al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\n",
      "text/plain": [
       "<Figure size 576x432 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.rcParams['font.sans-serif'] = ['SimHei']\n",
    "def plot_roc_curve(fpr, tpr, label=None):\n",
    "    plt.plot(fpr, tpr, linewidth=2, label=label)\n",
    "    plt.plot([0, 1], [0, 1], 'k--')\n",
    "    plt.axis([0, 1, 0, 1])\n",
    "    plt.xlabel('假正类率', fontsize=16)\n",
    "    plt.ylabel('真正类率', fontsize=16)\n",
    "\n",
    "plt.figure(figsize=(8, 6))\n",
    "plot_roc_curve(fpr, tpr)\n",
    "\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 125,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.9657031622840275"
      ]
     },
     "execution_count": 125,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 计算曲线下面积AUC，虚线是随机分类0.5到1\n",
    "from sklearn.metrics import roc_auc_score\n",
    "\n",
    "roc_auc_score(y_train_5, y_scores)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "* 召回率TPR越高，分类器的假正类FPR就越多\n",
    "* 虚线表示纯随机分类器的ROC曲线，好的分类器应该远离这条线，向左上角\n",
    "* 是使用精度/召回率 PR曲线，还是使用ROC，关键在于 正类非常少或者更关注假正类而不是假负类，选择PR，反之ROC\n",
    "* 例如：前面例子ROC曲线很不错是因为跟负类 非5 相比， 正类 数据5 数量真的很少\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 训练随机森林分类器，比较SGD分类器的ROC曲线和ROC AUC分数"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "* 获取训练集中每个实例的分数\n",
    "* RandomForestClassifier 没有descision_function(),但是拥有dict_proda()方法，sklearn中分类器都有这两个中的一个\n",
    "* dict_proda返回一个矩阵，每行一个实例，每列代表一个类别的概率，比如这个图片 70%是5"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 130,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[1., 0.],\n",
       "       [1., 0.],\n",
       "       [1., 0.],\n",
       "       ...,\n",
       "       [1., 0.],\n",
       "       [1., 0.],\n",
       "       [1., 0.]])"
      ]
     },
     "execution_count": 130,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from sklearn.ensemble import RandomForestClassifier\n",
    "forest_clf = RandomForestClassifier(n_estimators=10,random_state=42)\n",
    "y_probas_forest = cross_val_predict(forest_clf,X_train,y_train_5,cv=3,method='predict_proba')\n",
    "y_probas_forest"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 133,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([0., 0., 0., ..., 0., 0., 0.])"
      ]
     },
     "execution_count": 133,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 绘制ROC曲线，需要决策值不是概率，直接使用正类的概率作为决策值：\n",
    "y_scores_forest = y_probas_forest[:,1]\n",
    "y_scores_forest"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 134,
   "metadata": {},
   "outputs": [],
   "source": [
    "fpr_forest, tpr_forest, thresholds_forest = roc_curve(y_train_5,y_scores_forest)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 135,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 576x432 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.figure(figsize=(8, 6))\n",
    "plt.plot(fpr, tpr, \"b:\", linewidth=2, label=\"SGD\")\n",
    "plot_roc_curve(fpr_forest, tpr_forest, \"Random Forest\")\n",
    "plt.legend(loc=\"lower right\", fontsize=16)\n",
    "plt.show()\n",
    "# 从图可以得出随机森林比SGD的效果好"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 136,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.9927571179339292"
      ]
     },
     "execution_count": 136,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "roc_auc_score(y_train_5,y_scores_forest)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 139,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.9852455406298172"
      ]
     },
     "execution_count": 139,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "y_train_pred_forest = cross_val_predict(forest_clf,X_train,y_train_5,cv=3)\n",
    "precision_score(y_train_5,y_train_pred_forest)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 140,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.8253089835823649"
      ]
     },
     "execution_count": 140,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "recall_score(y_train_5,y_train_pred_forest)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "y_train_pred_forest"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 总结\n",
    "* 选择合适的指标利用交叉验证来对分类器进行评估\n",
    "* 选择满足需求的精度/召回率权衡\n",
    "* 使用ROC曲线和ROC AUC分数比较多个模型"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 多类别分类器\n",
    "* 尝试5 之外的检测\n",
    "* 多类别分类器 区分两个以上的类别\n",
    "* 随机森里和朴素贝叶斯可以直接处理多个类别\n",
    "* 支持向量机svm和线性分类器只可以处理二元分类器"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 解决方案\n",
    "1. 将数字图片分类0到9，训练10个二元分类器，每个数字一个，检测一张图片时，获取每个分类器的决策分数，哪个最高属于哪个，称为一对多OvA\n",
    "2. 为每一对数字训练一个二元分类器，区分0，1 区分0，2 区分1，2 称为一对一OvO策略，存在N个类别，需要N*（N-1）/2个分类器，最后看哪个类别获胜最多\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 优缺点\n",
    "* OvO 只需要用到部分训练集对其必须区分两个类别进行训练\n",
    "* 对于较小训练集合OvO比较有优势， 大训练集合 OvA 速度快，所以OvA更常用，比如svm 在数据规模扩大时表现糟糕\n",
    "* sklearn 检查到使用二元分类算法进行多类别分类任务，会自动运行OvA，SVM分类器除外"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 149,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([6.])"
      ]
     },
     "execution_count": 149,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "sgd_clf.fit(X_train, y_train)\n",
    "sgd_clf.predict([X[38000]])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 148,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "6.0"
      ]
     },
     "execution_count": 148,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "y[38000]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 150,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([6.])"
      ]
     },
     "execution_count": 150,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "forest_clf.fit(X_train, y_train)\n",
    "sgd_clf.predict([X[38000]])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 152,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0., 0., 0., 0., 0., 0., 1., 0., 0., 0.]])"
      ]
     },
     "execution_count": 152,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 随机森林直接将实例分为多个类别，调用predict_proba()可以获得分类器将每个实例分类为每个类别的概率列表\n",
    "forest_clf.predict_proba([X[38000]])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 153,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "D:\\Anaconda3\\lib\\site-packages\\sklearn\\linear_model\\stochastic_gradient.py:128: FutureWarning: max_iter and tol parameters have been added in <class 'sklearn.linear_model.stochastic_gradient.SGDClassifier'> in 0.19. If both are left unset, they default to max_iter=5 and tol=None. If tol is not None, max_iter defaults to max_iter=1000. From 0.21, default max_iter will be 1000, and default tol will be 1e-3.\n",
      "  \"and default tol will be 1e-3.\" % type(self), FutureWarning)\n",
      "D:\\Anaconda3\\lib\\site-packages\\sklearn\\linear_model\\stochastic_gradient.py:128: FutureWarning: max_iter and tol parameters have been added in <class 'sklearn.linear_model.stochastic_gradient.SGDClassifier'> in 0.19. If both are left unset, they default to max_iter=5 and tol=None. If tol is not None, max_iter defaults to max_iter=1000. From 0.21, default max_iter will be 1000, and default tol will be 1e-3.\n",
      "  \"and default tol will be 1e-3.\" % type(self), FutureWarning)\n",
      "D:\\Anaconda3\\lib\\site-packages\\sklearn\\linear_model\\stochastic_gradient.py:128: FutureWarning: max_iter and tol parameters have been added in <class 'sklearn.linear_model.stochastic_gradient.SGDClassifier'> in 0.19. If both are left unset, they default to max_iter=5 and tol=None. If tol is not None, max_iter defaults to max_iter=1000. From 0.21, default max_iter will be 1000, and default tol will be 1e-3.\n",
      "  \"and default tol will be 1e-3.\" % type(self), FutureWarning)\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "array([0.86237752, 0.85709285, 0.87218083])"
      ]
     },
     "execution_count": 153,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 使用交叉验证评估SGD的准确率\n",
    "cross_val_score(sgd_clf, X_train, y_train, cv=3, scoring=\"accuracy\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 159,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "D:\\Anaconda3\\lib\\site-packages\\sklearn\\linear_model\\stochastic_gradient.py:128: FutureWarning: max_iter and tol parameters have been added in <class 'sklearn.linear_model.stochastic_gradient.SGDClassifier'> in 0.19. If both are left unset, they default to max_iter=5 and tol=None. If tol is not None, max_iter defaults to max_iter=1000. From 0.21, default max_iter will be 1000, and default tol will be 1e-3.\n",
      "  \"and default tol will be 1e-3.\" % type(self), FutureWarning)\n",
      "D:\\Anaconda3\\lib\\site-packages\\sklearn\\linear_model\\stochastic_gradient.py:128: FutureWarning: max_iter and tol parameters have been added in <class 'sklearn.linear_model.stochastic_gradient.SGDClassifier'> in 0.19. If both are left unset, they default to max_iter=5 and tol=None. If tol is not None, max_iter defaults to max_iter=1000. From 0.21, default max_iter will be 1000, and default tol will be 1e-3.\n",
      "  \"and default tol will be 1e-3.\" % type(self), FutureWarning)\n",
      "D:\\Anaconda3\\lib\\site-packages\\sklearn\\linear_model\\stochastic_gradient.py:128: FutureWarning: max_iter and tol parameters have been added in <class 'sklearn.linear_model.stochastic_gradient.SGDClassifier'> in 0.19. If both are left unset, they default to max_iter=5 and tol=None. If tol is not None, max_iter defaults to max_iter=1000. From 0.21, default max_iter will be 1000, and default tol will be 1e-3.\n",
      "  \"and default tol will be 1e-3.\" % type(self), FutureWarning)\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "array([0.90666867, 0.91109555, 0.91023654])"
      ]
     },
     "execution_count": 159,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 将输入进行简单缩放 ，可以得到准确率 90 %以上\n",
    "from sklearn.preprocessing import StandardScaler\n",
    "scaler = StandardScaler()\n",
    "X_train_scaled = scaler.fit_transform(X_train.astype(np.float64))\n",
    "cross_val_score(sgd_clf, X_train_scaled, y_train, cv=3, scoring=\"accuracy\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 错误分析"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 项目流程\n",
    "1. 探索数据准备的选项\n",
    "2. 尝试多个模型\n",
    "3. 选择最佳模型并用GridSearchCV对参数进行微调\n",
    "4. 尽可能自动化"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 确定了一个相对合适的模型，进一步优化，分析其错误类型\n",
    "* 查看混淆矩阵\n",
    "* 使用cross_val_predict()进行预测\n",
    "* 调用confusion_matrix()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 161,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "D:\\Anaconda3\\lib\\site-packages\\sklearn\\linear_model\\stochastic_gradient.py:128: FutureWarning: max_iter and tol parameters have been added in <class 'sklearn.linear_model.stochastic_gradient.SGDClassifier'> in 0.19. If both are left unset, they default to max_iter=5 and tol=None. If tol is not None, max_iter defaults to max_iter=1000. From 0.21, default max_iter will be 1000, and default tol will be 1e-3.\n",
      "  \"and default tol will be 1e-3.\" % type(self), FutureWarning)\n",
      "D:\\Anaconda3\\lib\\site-packages\\sklearn\\linear_model\\stochastic_gradient.py:128: FutureWarning: max_iter and tol parameters have been added in <class 'sklearn.linear_model.stochastic_gradient.SGDClassifier'> in 0.19. If both are left unset, they default to max_iter=5 and tol=None. If tol is not None, max_iter defaults to max_iter=1000. From 0.21, default max_iter will be 1000, and default tol will be 1e-3.\n",
      "  \"and default tol will be 1e-3.\" % type(self), FutureWarning)\n",
      "D:\\Anaconda3\\lib\\site-packages\\sklearn\\linear_model\\stochastic_gradient.py:128: FutureWarning: max_iter and tol parameters have been added in <class 'sklearn.linear_model.stochastic_gradient.SGDClassifier'> in 0.19. If both are left unset, they default to max_iter=5 and tol=None. If tol is not None, max_iter defaults to max_iter=1000. From 0.21, default max_iter will be 1000, and default tol will be 1e-3.\n",
      "  \"and default tol will be 1e-3.\" % type(self), FutureWarning)\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "array([[5735,    2,   22,   12,   10,   45,   44,    8,   41,    4],\n",
       "       [   1, 6445,   48,   23,    6,   41,    7,   15,  147,    9],\n",
       "       [  62,   35, 5313,   99,   84,   19,   94,   60,  179,   13],\n",
       "       [  45,   43,  127, 5363,    4,  222,   40,   57,  133,   97],\n",
       "       [  21,   28,   32,    6, 5358,    8,   60,   27,   87,  215],\n",
       "       [  74,   37,   31,  192,   69, 4603,  113,   28,  175,   99],\n",
       "       [  36,   28,   42,    2,   41,   98, 5620,    6,   45,    0],\n",
       "       [  28,   17,   73,   24,   60,   11,    6, 5795,   17,  234],\n",
       "       [  49,  138,   67,  159,   14,  170,   55,   23, 5035,  141],\n",
       "       [  44,   33,   28,   86,  156,   33,    3,  194,   79, 5293]],\n",
       "      dtype=int64)"
      ]
     },
     "execution_count": 161,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "y_train_pred = cross_val_predict(sgd_clf,X_train_scaled,y_train,cv=3)\n",
    "# 得到混淆矩阵\n",
    "conf_mx = confusion_matrix(y_train,y_train_pred)\n",
    "conf_mx"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 162,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 288x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "# 使用matplotlib的matshow 函数来查看混淆矩阵的图像表示\n",
    "# 数量越多的区域越靠近白色，数量越少的区域就越靠近黑色\n",
    "# cmap 颜色区域\n",
    "plt.matshow(conf_mx,cmap=plt.cm.gray)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 163,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 看起来不错，大多数图片都在主对角线上，说明它们被正确分类\n",
    "# 数字5 看起来比较暗，说明1. 数字5图片较少  2. 分类器在数字5上执行效果不如其他数字上好\n",
    "# 假设把焦点放在错误上，为取得错误率，而不是错误绝对值，需要将混淆矩阵中每个值除以相应类别中的图片数量\n",
    "# keepdims=True保持矩阵的多维特性\n",
    "row_sums = conf_mx.sum(axis = 1,keepdims=True)\n",
    "norm_conf_mx = conf_mx/row_sums"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 164,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 288x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "# 用0填充对角线 只保留错误，重新绘制\n",
    "np.fill_diagonal(norm_conf_mx,0)\n",
    "plt.matshow(norm_conf_mx,cmap = plt.cm.gray)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 每行代表实际类别，每列代表预测类别\n",
    "# 8，9列比较亮，说明许多图片被错误的分类为数字8，9\n",
    "# 类别8，9行也偏亮，说明数字8和9经常会跟其他数字混淆\n",
    "# 有些很暗，比如行1，大多数数字1都被正确的分类，一些和8混淆\n",
    "# 5和3是错误最多的"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
